package cn.lastcrdg.testballview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;

import static android.graphics.Color.RED;

/**
 * author：liluo
 * e-mail：lastcrazysun@163.com
 * company：cusc
 * date：2017/10/13 15:34
 * description：
 */

public class BubbleView extends View {
    private static final String TAG = BubbleView.class.getSimpleName();
    private final float PConst = 0.551915024494f;
    private int width;
    private int height;
    private Paint mPaint;
    private Path mPath;
    //X轴及其上下辅助点的坐标，2组共6个点(顺时针)
    private HPoint p1, p3;
    //Y轴及其上下辅助点的坐标，2组共6个点
    private VPoint p2, p4;
    //半径
    private float r;
    //辅助点的长度
    private float c;
    //动画执行回调时间0~1.0
    private float mInterpolatedTime = 0;
    //动画执行总时间
    private int duration;
    //目标辅助点长度
    private float cDistance;

    public BubbleView(Context context) {
        this(context, null);
    }

    public BubbleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BubbleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        initPaint();
        initStyle();
    }

    private void initStyle() {
        setR(50f);
        setDuration(5000);

        c = r * PConst;
        setcDistance(c * 0.45f);

        mPath = new Path();
        p1 = new HPoint();
        p3 = new HPoint();
        p2 = new VPoint();
        p4 = new VPoint();
    }

    private void initPaint() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(RED);
        mPaint.setStrokeWidth(1);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        width = getWidth();
        height = getHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        initCircle();
        canvas.translate(r, r);
        if (mInterpolatedTime >= 0 && mInterpolatedTime <= 0.2f) {
            change1(mInterpolatedTime);
        } else if (mInterpolatedTime > 0.2f && mInterpolatedTime <= 0.5f) {
            change2(mInterpolatedTime);
        } else if (mInterpolatedTime > 0.5f && mInterpolatedTime <= 0.8f) {
            change3(mInterpolatedTime);
        } else if (mInterpolatedTime > 0.8f && mInterpolatedTime <= 0.9f) {
            change4(mInterpolatedTime);
        } else {
            change5(mInterpolatedTime);
        }

        //执行平移动画
        float offset = 0;
        if (mInterpolatedTime > 0.2f) {
            //动画过程整体平移r距离，可评议长度剩下width-2*r-r
            offset = (width - 3 * r) * (mInterpolatedTime - 0.2f) * (5f / 4);
        }
        p1.adjustAllX(offset);
        p2.adjustAllX(offset);
        p3.adjustAllX(offset);
        p4.adjustAllX(offset);

        mPath.reset();
        mPath.moveTo(p1.x, p1.y);
        mPath.cubicTo(p1.bottom.x, p1.bottom.y, p2.right.x, p2.right.y, p2.x, p2.y);
        mPath.cubicTo(p2.left.x, p2.left.y, p3.bottom.x, p3.bottom.y, p3.x, p3.y);
        mPath.cubicTo(p3.top.x, p3.top.y, p4.left.x, p4.left.y, p4.x, p4.y);
        mPath.cubicTo(p4.right.x, p4.right.y, p1.top.x, p1.top.y, p1.x, p1.y);
        canvas.drawPath(mPath, mPaint);
    }

    public void setR(float r) {
        this.r = r;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    public void setcDistance(float cDistance) {
        this.cDistance = cDistance;
    }

    /**
     * 初始化圆形
     */
    private void initCircle() {
        p1.x = r;
        p1.y = 0;
        p1.top.set(r, -c);
        p1.bottom.set(r, c);

        p2.x = 0;
        p2.y = r;
        p2.left.set(-c, r);
        p2.right.set(c, r);

        p3.x = -r;
        p3.y = 0;
        p3.top.set(-r, -c);
        p3.bottom.set(-r, c);

        p4.x = 0;
        p4.y = -r;
        p4.left.set(-c, -r);
        p4.right.set(c, -r);
    }

    private void change1(float time) {//0-0.2
        initCircle();
        time = time * 5;
        //拉长圆形右半部分，当time==0.2时，X被拉长一倍
        p1.setX(r + r * time);
        p1.adjustY(cDistance / 2 * time);
    }

    private void change2(float time) {//0.2-0.5
        change1(0.2f);
        time = (time - 0.2f) * 10f / 3f;
        //平移Y,是左右拉伸相同成椭圆形
        p2.adjustAllX(r / 2 * time);
        p4.adjustAllX(r / 2 * time);
        p1.adjustY(cDistance / 2 * time);
        p3.adjustY(cDistance * time);
    }

    private void change3(float time) {//0.5-0.8
        change2(0.5f);
        time = (time - 0.5f) * 10f / 3f;
        p2.adjustAllX(r / 2 * time);
        p4.adjustAllX(r / 2 * time);
        p1.adjustY(-cDistance * time);
        p3.adjustY(-cDistance / 2 * time);
    }

    private void change4(float time) {//0.8-0.9
        change3(0.8f);
        time = (time - 0.8f) * 10f;
        p3.setX(-r + r * time);
        p3.adjustY(-cDistance / 2 * time);
    }

    private void change5(float time) {//0.9-1.0
        change4(0.9f);
        time = (time - 0.9f) * 10f;
        p3.adjustAllX(r / 2 * (float) (Math.sin(Math.PI * time)));
    }

    private class HPoint {
        PointF top = new PointF();
        PointF bottom = new PointF();
        float x;
        float y;

        public void setX(float x) {
            this.x = x;
            this.top.x = x;
            this.bottom.x = x;
        }

        public void adjustAllX(float offset) {
            x += offset;
            top.x += offset;
            bottom.x += offset;
        }

        public void adjustY(float offset) {
            // 默认是增加
            this.top.y -= offset;
            this.bottom.y += offset;
        }

        @Override
        public String toString() {
            return "HPoint{" +
                    "top=" + top +
                    ", bottom=" + bottom +
                    ", x=" + x +
                    ", y=" + y +
                    '}';
        }
    }

    private class VPoint {
        PointF left = new PointF();
        PointF right = new PointF();
        float x;
        float y;

        public void adjustAllX(float offset) {
            x += offset;
            left.x += offset;
            right.x += offset;
        }

        @Override
        public String toString() {
            return "VPoint{" +
                    "left=" + left +
                    ", right=" + right +
                    ", x=" + x +
                    ", y=" + y +
                    '}';
        }
    }

    public void startAnimation() {
        MytranslateAnimation animation = new MytranslateAnimation();
        animation.setDuration(duration);

        animation.setInterpolator(new AccelerateDecelerateInterpolator());
        startAnimation(animation);
    }

    private class MytranslateAnimation extends Animation {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);

            mInterpolatedTime = interpolatedTime;
            invalidate();
        }
    }
}
